package cn.wdm.ymcc.service.impl;

import cn.wdm.ymcc.domain.*;
import cn.wdm.ymcc.exception.GloablException;
import cn.wdm.ymcc.feign.LoginFeignClient;
import cn.wdm.ymcc.mapper.UserMapper;
import cn.wdm.ymcc.result.JSONResult;
import cn.wdm.ymcc.service.IUserAccountService;
import cn.wdm.ymcc.service.IUserBaseInfoService;
import cn.wdm.ymcc.service.IUserService;
import cn.wdm.ymcc.util.AssertUtil;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import io.seata.spring.annotation.GlobalTransactional;
import org.assertj.core.api.Assert;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.Date;

/**
 * <p>
 * 会员登录账号 服务实现类
 * </p>
 *
 * @author lao.zhang
 * @since 2022-07-15
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private LoginFeignClient loginFeignClient;
    @Autowired
    private IUserBaseInfoService userBaseInfoService;
    @Autowired
    private IUserAccountService userAccountService;


    @Override
    @GlobalTransactional
    public void phoneRegister(VerifycodeDto dto) {
        //非空校验
        String phone = dto.getMobile();
        String smsCode = dto.getSmsCode();
        if (StringUtils.isEmpty(phone)||StringUtils.isEmpty(smsCode)){
            throw new GloablException("内容不能为空！");
        }
        //短信验证码校验
        //1.从redis中获取存入的短信验证码 没有获取到说明短信验证码过期了
        //smsCodeInRedisValue 9527:648979864894
        Object smsCodeInRedisValue = redisTemplate.opsForValue().get("register" + phone);
        if (smsCodeInRedisValue == null) {
            throw new GloablException("你的短信验证码过期了");
        }
        //不为空 redis中的短信验证码不为空 判断两次的输入是否一致
        if (!smsCode.equalsIgnoreCase(smsCodeInRedisValue.toString().split(":")[0])) {
            throw new GloablException("你输入的短信验证码有误");
        }
        //手机号不能被注册
        User userTem = selectUserByPhone(dto.getMobile());
        AssertUtil.isNull(userTem,"手机号已经被注册");

        //保存user+logininfo
        //1.先保存t_login 在uaa中，同时还要返回自增的
        JSONResult jsonResult=saveLogin(dto);
        //2.断言参数
        AssertUtil.isTrue(jsonResult.isSuccess(),jsonResult.getMessage());
        //断言新增返回的数据是否为空，为空就报错
        AssertUtil.isNotNull(jsonResult.getData(),"登录信息保存失败！");
        Long loginId = Long.valueOf(jsonResult.getData().toString());
        //保存user
        User user=saveUser(loginId, dto.getMobile());
        AssertUtil.isNotNull(user.getId(),"用户保存失败！！");
        //保存userBaseInfo
        initUserInfo(user.getId(),dto.getRegChannel());
        //保存userAccount
        initUserAccount(user.getId());
    }

    /**
     * 根据电话号码查询数据库中是否已经存在 查t_user
     * @param mobile
     * @return
     */
    private User selectUserByPhone(String mobile) {
        Wrapper<User> tWrapper = new EntityWrapper();
        tWrapper.eq("phone",mobile);  // where phone = 123123
        return selectOne(tWrapper);
    }
    /**
     * 在新增user的时候 级联保存account账户，账户的Id为userId
     * @param id
     */
    private void initUserAccount(Long id) {
        UserAccount account = new UserAccount();
        account.setId(id);
        account.setCreateTime(new Date().getTime());
        userAccountService.insert(account);
    }
    /**
     * 在新增user的时候 级联保存base-info的信息 id为userId
     * @param id
     * @param regChannel
     */
    private void initUserInfo(Long id, Integer regChannel) {
        UserBaseInfo info = new UserBaseInfo();
        info.setId(id);
        info.setCreateTime(new Date().getTime());
        info.setRegChannel(regChannel);//注册渠道
        userBaseInfoService.insert(info);
    }
    /**
     * 在新增user，返回自增的Id
     * @param loginId
     * @param mobile
     * @return
     */
    private User saveUser(Long loginId,String mobile) {
        User user = new User();
        user.setLoginId(loginId);
        user.setPhone(mobile);
        user.setNickName(mobile);
        user.setCreateTime(new Date().getTime());
        insert(user);
        return user;
    }
    /**
     * 首先保存 t_login 返回其login_id，因为保存user的时候要保存
     * @param dto
     * @return
     */
    private JSONResult saveLogin(VerifycodeDto dto) {
        Login login = new Login();
        login.setUsername(dto.getMobile());
        login.setPassword(dto.getPassword());
        login.setType(1);
        JSONResult jsonResult = loginFeignClient.saveOrUpdate(login);
        return jsonResult;
    }
}
